﻿using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ocelot.Admin.Api.Application
{
    public class ConsulHub : Hub
    {
        private readonly IConsulService _consulService;
        private readonly IGlobalConfigurationService _globalConfigurationService;
        private readonly IProjectService _projectService;
        private readonly IRouteService _routeService;

        public ConsulHub(IConsulService consulService, IGlobalConfigurationService globalConfigurationService,
            IProjectService projectService, IRouteService routeService)
        {
            _consulService = consulService;
            _globalConfigurationService = globalConfigurationService;
            _projectService = projectService;
            _routeService = routeService;
        }

        public async Task SysnToConsulAsync(string key, string dc)
        {
            if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(dc))
            {
                await Clients.Caller.SendAsync("SysnToConsulMessage", $"consul配置未选中");
                return;
            }
            var ocelotConfig = new OcelotConfigurationDto();
            // 获取全局变量
            var globalConfiguration = await _globalConfigurationService.GetGlobalConfigurationAsync();
            if (globalConfiguration != null)
            {
                await Clients.Caller.SendAsync("SysnToConsulMessage", $"获取全局配置成功，当前全局配置{(globalConfiguration.Enabled ? "已启用" : "已禁用")}");
                if (globalConfiguration.Enabled)
                {
                    var globalConfigurationDto = globalConfiguration.Adapt<GlobalConfigurationDto>();
                    ocelotConfig.GlobalConfiguration = globalConfigurationDto;
                }
            }
            var projects = await _projectService.GetProjectsAsync();
            if (projects.Count == 0)
            {
                await Clients.Caller.SendAsync("SysnToConsulMessage", $"未查询到可用项目，停止同步，请检查后重试");
                return;
            }
            var allRoutes = new List<RouteDto>();
            foreach (var project in projects)
            {
                if (project.Routes.Count > 0)
                {
                    var routeDtos = project.Routes.OrderByDescending(o => o.Sort).Adapt<List<RouteDto>>();
                    allRoutes.AddRange(routeDtos);
                }
            }

            var configRoutes = allRoutes.Adapt<List<ConfigRouteDto>>();
            ocelotConfig.Routes = configRoutes;

            var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
            var ocelotConfigJson = Newtonsoft.Json.JsonConvert.SerializeObject(ocelotConfig, Formatting.Indented, jSetting);
            await Clients.Caller.SendAsync("SysnToConsulMessage", $"构造ocelot配置成功");
            var settingBak = await _consulService.GetLastSettingBakAsync(key, dc);
            var settingJsonHashCode = settingBak != null ? settingBak.BakJson.GetHashCode() : 0;
            var currentJson = await _consulService.GetConsulKeyValueAsync(key, dc);
            //如果当前配置与要设置的配置一致，则不进行同步
            if (ocelotConfigJson.GetHashCode() == currentJson.GetHashCode())
            {
                await Clients.Caller.SendAsync("SysnToConsulMessage", $"与线上内容一致，同步取消");
                return;
            }

            if (settingJsonHashCode == currentJson.GetHashCode())
            {
                await Clients.Caller.SendAsync("SysnToConsulMessage", $"与上次备份内容一致，跳过备份");
            }
            else
            {
                await Clients.Caller.SendAsync("SysnToConsulMessage", $"进行配置备份");
                var bakResult = await _consulService.InsertSettingBakAsync(key, dc, currentJson, "同步备份");
                await Clients.Caller.SendAsync("SysnToConsulMessage", bakResult ? "备份完成" : "备份失败，同步中断");
                if (!bakResult)
                    return;
            }

            var editResult = await _consulService.EditConsulKeyValueAsync(key, dc, ocelotConfigJson);
            await Clients.Caller.SendAsync("SysnToConsulMessage", editResult ? "同步完成" : "同步失败");
        }
    }
}
